#include "OpenglAppFramework/inc/Scene.h"
#include "OpenglAppFramework/inc/GameObject.h"
#include "OpenglAppFramework/inc/TextureManager.h"
#include "OpenglAppFramework/inc/Shader.h"
#include "OpenglAppFramework/inc/PlugIn/Material.h"
#include "OpenglAppFramework/inc/PlugIn/Mesh.h"
#include "OpenglAppFramework/inc/PlugIn/LightSource.h"
#include "OpenglAppFramework/inc/Utils.h"
#include <iostream>

Scene::Scene() {
}

Scene::~Scene() {
    for(auto kv : m_objs) {
        delete kv.second;
    }
}

void Scene::setGameObject(GameObject* obj) {
    m_objs[obj->name()] = obj;
    if(obj->getCamera() != nullptr) {
        m_camera_objs[obj->name()] = obj;
    }
    if(obj->getLightSource() != nullptr) {
        m_light_source[obj->name()] = obj;
        if(obj->getLightSource()->isShadowEnabled() == true) {
            m_shadow_lights[obj->name()] = obj;
        }
    }
    if(obj->getMesh() != nullptr) {
        if(obj->getInstancingPlugIn() != nullptr) {
            m_instancing_objs[obj->name()] = obj;
        }
        else if(obj->getMaterial() != nullptr) {
            m_normal_objs[obj->name()] = obj;
        }
    }
}

GameObjects& Scene::objects() {
    return m_objs;
}

OpenglEnv& Scene::env() {
    return m_env;
}

GameObject* Scene::getObjectByName(const std::string& name) {
    auto it = m_objs.find(name);
    if(it == m_objs.end()) {
        return nullptr;
    }
    return it->second;
}

GameObjects& Scene::cameraObjects()         { return m_camera_objs; }
GameObjects& Scene::lightSourceObjects()    { return m_light_source; }
GameObjects& Scene::shadowLightObjects()    { return m_shadow_lights;}
GameObjects& Scene::normalObjects()         { return m_normal_objs; }
GameObjects& Scene::instancingObjects()     { return m_instancing_objs; }

bool Scene::hasInstancing() const {
    return m_instancing_objs.size() > 0;
}
